<?php

namespace app\jobs;

use app\helper\Log;
use think\queue\Job as ThinkQueueJob;

abstract class Job
{

    // 失败原因
    protected $failMsg = '';

    /**
     * 获取任务名
     *
     * @return string
     */
    abstract protected function getName(): string;

    /**
     * 执行任务
     *
     * @param ThinkQueueJob $job 任务
     * @param mixed $data 任务数据
     * @return bool
     */
    abstract protected function exec(ThinkQueueJob $job, $data): bool;

    public function fire(ThinkQueueJob $job, $data)
    {
        $startTime = microtime(true);
        $this->writeLog('开始执行');

        try {
            $this->writeLog('数据: ' . json_encode($data, JSON_UNESCAPED_UNICODE));
            $res = $this->exec($job, $data);
            if ($res) {
                $this->writeLog('执行成功，耗时: ' . round(microtime(true) - $startTime, 3) . '秒' . PHP_EOL);
            } else {
                $this->failed($data);
            }
        } catch (\Exception $e) {
            exception_log('队列任务执行失败', $e);
            $this->failMsg = $e->getMessage() . PHP_EOL . $e->getFile() . PHP_EOL . $e->getLine();
            $this->failed($data);
        }

        $job->delete();
    }

    public function failed($data)
    {
        $this->writeLog('执行失败,失败原因: ' . $this->failMsg . ', ' . json_encode($data, JSON_UNESCAPED_UNICODE) . PHP_EOL);
    }

    public function writeLog($str)
    {
        Log::writeLog('队列任务/' . $this->getName(), $str);
    }

}